﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gencode.VECore;
using System.Windows;
using System.Windows.Input;
using Gencode.VECore.VectorShape;

namespace Gencode.VECore.Tools
{
	public class GrabTool : VectorTool
	{
        
		private enum SelectionMode
		{
			None,
			GroupSelection, // group selection is active
			Move,           // object(s) are moves
			Size            // object is resized
		}

		SelectionMode selectMode = SelectionMode.None;
        // Object which is currently resized:
        VECShape resizedObject;
		int resizeHandleNumber = 0;

        // Keep state about last and current point (used to move and resize objects)
        Point lastPoint = new Point(0, 0);
        Point startPoint = new Point(0, 0);

        Gencode.VECore.History.StateChangeCommand changeCmd;
        bool shapeWasMoved;
        VECRectangle selectionRectangle;

        public override void OnMouseLeftButtonDown(CanvasDocument sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			var point = Mouse.GetPosition(sender);
            changeCmd = null;
            shapeWasMoved = false;

			// Test for resizing (only if control is selected, cursor is on the handle)
            //foreach (VECShape shape in CanvasManager.SelectedLayer.ShapeList.Selection)
            foreach (VECShape shape in sender.SelectedLayer.ShapeList.Selection)
            {
                int handleNumber = shape.HitTest(point);

                if (handleNumber > 0)
                {
                    selectMode = SelectionMode.Size;

                    // keep resized object in class member
                    resizedObject = shape;
                    resizeHandleNumber = handleNumber;

                    // Since we want to resize only one object, unselect all other objects
                    //CanvasManager.SelectedLayer.ShapeList.UnselectAll();
                    sender.SelectedLayer.ShapeList.UnselectAll();
                    shape.Selected = true;

                    changeCmd = new Gencode.VECore.History.StateChangeCommand(sender.SelectedLayer.ShapeList);

                    break;
                }
            }

            // Test for move (cursor is on the object)
            if (selectMode == SelectionMode.None)
            {
                int n1 = sender.SelectedLayer.ShapeList.Count;
                VECShape shape = null;

                for (int i = 0; i < n1; i++)
                {
                    if (sender.SelectedLayer.ShapeList[i].HitTest(point) == 0)
                    {
                        shape = sender.SelectedLayer.ShapeList[i];
                        break;
                    }
                }

                if (shape != null)
                {
                    selectMode = SelectionMode.Move;

                    // Unselect all if Ctrl is not pressed and clicked object is not selected yet
                    if (!((Keyboard.IsKeyDown(Key.LeftCtrl)) || (Keyboard.IsKeyDown(Key.RightCtrl))) && !shape.Selected)
                        sender.SelectedLayer.ShapeList.UnselectAll();

                    // Select clicked object
                    shape.Selected = true;

                    changeCmd = new Gencode.VECore.History.StateChangeCommand(sender.SelectedLayer.ShapeList);

                    sender.SelectedLayer.Cursor = Cursors.SizeAll;
                }
            }

            // group selection
            if (selectMode == SelectionMode.None)
            {
                // click on background so unselect all
                if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                    sender.SelectedLayer.ShapeList.UnselectAll();

                selectMode = SelectionMode.GroupSelection;
            }

            lastPoint.X = point.X;
            lastPoint.Y = point.Y;
            startPoint.X = point.X;
            startPoint.Y = point.Y;

            // Draw selection rectangle in initial position
            if (selectMode == SelectionMode.GroupSelection)
            {
                
                if (selectionRectangle != null)
                    sender.RemoveUnregisteredShape(selectionRectangle);

                selectionRectangle = new VECRectangle(startPoint.X, startPoint.Y, 1, 1);
                selectionRectangle.Fill = System.Windows.Media.Brushes.Transparent;
                selectionRectangle.Stroke = System.Windows.Media.Brushes.Black;
                selectionRectangle.StrokeThickness = 0.5;
                selectionRectangle.StrokeDashArray.Add(5);
                selectionRectangle.StrokeDashArray.Add(10);

                sender.AddUnregisteredShape(selectionRectangle);
            }
		}

        public override void OnMouseMove(CanvasDocument sender, System.Windows.Input.MouseEventArgs e)
		{
            var point = Mouse.GetPosition(sender);
            shapeWasMoved = true;

            // set cursor when mouse button is not pressed
            if (e.LeftButton == MouseButtonState.Released)
            {
                Cursor cursor = null;

                for (int i = 0; i < sender.SelectedLayer.ShapeList.Count; i++)
                {
                    int n = sender.SelectedLayer.ShapeList[i].HitTest(point);

                    if (n > 0)
                    {
                        cursor = sender.SelectedLayer.ShapeList[i].GetHandleCursor(n);
                        break;
                    }
                }

                if (cursor == null)
                    cursor = Cursors.Arrow;

                sender.SelectedLayer.Cursor = cursor;

                return;
            }

            // resize
            if (selectMode == SelectionMode.Size)
            {
                if (resizedObject != null)
                {
                    resizedObject.MoveHandle(point, resizeHandleNumber);
                }
            }

            // Find difference between previous and current position
            int dx = (int)(point.X - lastPoint.X);
            int dy = (int)(point.Y - lastPoint.Y);

            lastPoint.X = point.X;
            lastPoint.Y = point.Y;

            // move
            if (selectMode == SelectionMode.Move)
            {
                foreach (VECShape shape in sender.SelectedLayer.ShapeList.Selection)
                {
                    shape.Move(dx, dy);
                }
            }
            
            if (selectMode == SelectionMode.GroupSelection)
            {
                //resize the selectionrectangle
                if (selectionRectangle != null)
                {
                    System.Windows.Point m = Mouse.GetPosition(sender);

                    if (m.Y > (selectionRectangle.Y + (selectionRectangle.Height / 2)) &&
                        m.X > (selectionRectangle.X + (selectionRectangle.Width / 2)))//lower right
                        selectionRectangle.MoveHandle(m, 3);
                    else if (m.Y > (selectionRectangle.Y + (selectionRectangle.Height / 2)) &&
                        m.X < (selectionRectangle.X + (selectionRectangle.Width / 2)))//lower left
                        selectionRectangle.MoveHandle(m, 4);
                    else if (m.Y < (selectionRectangle.Y + (selectionRectangle.Height / 2)) &&
                        m.X < (selectionRectangle.X + (selectionRectangle.Width / 2)))//upper left
                        selectionRectangle.MoveHandle(m, 1);
                    else//upper right
                        selectionRectangle.MoveHandle(m, 2);
                }

                return;
            }
            

            if (changeCmd != null && shapeWasMoved)
            {
                // Keep state after moving/resizing and add command to history
                changeCmd.NewState(sender.SelectedLayer.ShapeList);
                sender.AddCommandToHistory(changeCmd);
                changeCmd = null;
            }
		}

        public override void OnMouseLeftButtonUp(CanvasDocument sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (selectMode == SelectionMode.GroupSelection && selectionRectangle != null)
            {
                //select all objects contained in rectangle
                sender.SelectShapes(
                    VECRectangle.GetNormalizedRectangle(startPoint, lastPoint));

                sender.RemoveUnregisteredShape(selectionRectangle);
                selectionRectangle = null;
            }

            selectMode = SelectionMode.None;
            resizeHandleNumber = 0;
        }
	}
}
